package com.sbio.udiapp.ui;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.ObservableArrayList;
import androidx.databinding.ObservableList;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;

import cpcl.PrinterHelper;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

import com.alibaba.fastjson.JSONObject;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.StringUtils;
import com.sbio.udiapp.BuildConfig;
import com.sbio.udiapp.adapter.OutStockApplyAdapter;
import com.sbio.udiapp.common.bean.ExpressPage;
import com.sbio.udiapp.common.bean.ExpressType;
import com.sbio.udiapp.common.bean.RequestUniParam;
import com.sbio.udiapp.databinding.ActivityExpressBinding;
import com.sbio.udiapp.listener.ListAdapterListener;
import com.sbio.udiapp.net.api.ApiService;
import com.sbio.udiapp.net.bean.AjaxResult;
import com.sbio.udiapp.util.ApiServiceUtil;
import com.sbio.udiapp.util.CollectionUtils;
import com.sbio.udiapp.util.DialogUtil;
import com.sbio.udiapp.util.IntentUtil;
import com.sbio.udiapp.util.LogUtil;
import com.sbio.udiapp.util.SharedPreferencesUtil;
import com.sbio.udiapp.util.SoundPlayerUtil;
import com.sbio.udiapp.util.StringUtil;
import com.sbio.udiapp.util.ToastUtil;

import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

import javax.inject.Inject;


@AndroidEntryPoint
public class ExpressActivity extends AppCompatActivity implements ListAdapterListener {

    ActivityExpressBinding binding;

    @Inject
    ApiService apiService;

    ProgressDialog progressDialog;

    AtomicInteger progressCount = new AtomicInteger();

    private IntentFilter intentFilter;

    //总共的物流方式
    List<ExpressType> expressTypes;
    //选中的物流方式
    private ExpressType expressType;
    private BroadcastReceiver broadcastReceiver;
    ObservableList<String> nos = new ObservableArrayList<>();

    private ExpressPage expressPage;


    /**
     * 用于上传时的数据
     */
    ExpressPage expressPageCopy;

    OutStockApplyAdapter adapter;

    private boolean needSaveExpressPage;


    /**
     * 初始化进度条
     */
    private void initProgressDialog() {
        progressDialog = new ProgressDialog(ExpressActivity.this);
        progressDialog.setMessage("加载中..."); // 设置提示信息
        progressDialog.setCancelable(true); // 设置是否允许用户通过点击屏幕或按返回键取消对话框
        progressDialog.show(); // 显示对话框
    }

    private void showProcess() {
        progressCount.incrementAndGet();
        progressDialog.show();
    }

    private void hideProcess() {
        int count = progressCount.decrementAndGet();
        if (count <= 0) {
            progressDialog.hide();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityExpressBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);

        binding.getRoot().setOnClickListener(v -> {
            imm.hideSoftInputFromWindow(binding.waybillCount.getWindowToken(), 0); // 关闭键盘
            binding.waybillCount.clearFocus();

        });


        //初始化数据
        initData();

        //初始化进度条
        initProgressDialog();
        SharedPreferencesUtil.init(this);

        initPageNo();
        initSystemScanData();

        initExpressTypeWidget();

        //初始化nos监听器
        initNosListener();

        initToggleDataWidget();


        //绑定提交业务
        binding.submit.setOnClickListener(v -> {

            String waybillCount = binding.waybillCount.getText().toString();

            if (StringUtils.isEmpty(waybillCount)) {
                ToastUtil.showError("请先填写电子面单数量");
                return;
            }
            if (CollectionUtils.isEmpty(nos)) {
                ToastUtil.showError("请先扫码添加发货单");
                return;
            }

            int waybillCountInt = Integer.parseInt(waybillCount);

            String weightStr = binding.weight.getText().toString();
            double weight = 0;
            if (!StringUtils.isEmpty(weightStr)) {
                weight = Double.parseDouble(weightStr);
            }


            String requestUniParam = RequestUniParam.create("提交ExpressActivity").toJson();
            showProcess();
            double finalWeight = weight;
            ApiServiceUtil.enqueue(() -> apiService.havePrint(expressPage.getPageNo()), new Callback<AjaxResult>() {
                @Override
                public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {
                    hideProcess();
                    AjaxResult ajaxResult = response.body();
                    /*if (ajaxResult.getCode() == 500) {
                        List<String> nos = ajaxResult.getDataList(String.class);
                        String msg = "以下单据编号今天已经打印过了，还需要继续打印吗？\n" + String.join(",", nos);

                        DialogUtil.showCommonConfirmDialog(msg, () -> printExpressDeliveryNote(waybillCountInt, requestUniParam));
                    } else {
                        printExpressDeliveryNote(waybillCountInt, requestUniParam);
                    }*/

                    Map<String, Object> data = ajaxResult.getData(Map.class);
                    List<String> havePrintBillNos = (List<String>) data.get("havePrintBillNos");
                    boolean havePrintNosOfSameAddress = (Boolean) data.get("havePrintNosOfSameAddress");
                    AtomicInteger printFlag = new AtomicInteger();
                    if (havePrintBillNos.isEmpty() && !havePrintNosOfSameAddress) {
                        printExpressDeliveryNote(waybillCountInt, finalWeight, requestUniParam);
                        return;
                    }
                    StringBuilder msg = new StringBuilder();
                    List<String> msgs = new ArrayList<>();
                    if (!havePrintBillNos.isEmpty()) {
                        msgs.add("以下单据编号今天已经打印过了:\n" + String.join(",", havePrintBillNos));
                    }
                    if (havePrintNosOfSameAddress) {
                        msgs.add("该地址今天已经打印过快递单");
                    }
                    if (msgs.isEmpty()) {
                        printExpressDeliveryNote(waybillCountInt, finalWeight, requestUniParam);
                    } else {
                        for (int i = 0; i < msgs.size(); i++) {
                            msg.append((i + 1)).append(".").append(msgs.get(i)).append("\n");
                        }
                        DialogUtil.showCommonConfirmDialog(msg.toString(), () -> printExpressDeliveryNote(waybillCountInt, finalWeight, requestUniParam));
                    }


                }

                @Override
                public void onFailure(Call<AjaxResult> call, Throwable t) {
                    hideProcess();
                    DialogUtil.showErrorAlertDialog(t.getMessage());
                }
            });

        });
    }

    private void printExpressDeliveryNote(int waybillCountInt, double weight, String requestUniParam) {
        showProcess();
        long startTime = System.currentTimeMillis();
        ApiServiceUtil.enqueue(() -> apiService.printExpressDeliveryNote(expressPage.getPageNo(), expressType.getDictValue(), waybillCountInt, weight, requestUniParam), new Callback<AjaxResult>() {
            @Override
            public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {
                hideProcess();
                try {
                    AjaxResult ajaxResult = response.body();
                    if (ajaxResult.getCode() == 500) {
                        ToastUtil.showError(ajaxResult.getMsg());
                        return;
                    }
                    List<String> imageBase64s = ajaxResult.getDataListByClz(String.class);

                    for (String imageBase64 : imageBase64s) {

                        byte[] decode = Base64.getDecoder().decode(imageBase64);
                        Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length);

                        int s1 = 75 * 8;
                        int s2 = 105 * 8;

                        PrinterHelper.printAreaSize("0", String.valueOf(s1), String.valueOf(s2), String.valueOf(s2), "1");
                        PrinterHelper.printBitmapCPCL(bitmap, 0, 0, 0, 0, 0);
                        PrinterHelper.Form();
                        PrinterHelper.Print();
                    }
                    LogUtils.i("时间：", System.currentTimeMillis() - startTime);
                    if (ajaxResult.isSuccess()) {
                        ToastUtil.show("打印成功");
                        if (!BuildConfig.DEBUG) {
                            ExpressActivity.this.reset();
                        }
                    } else {
                        DialogUtil.showCommonAlertDialog("打印失败" + ajaxResult.getMsg());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    LogUtil.file("print", e.getMessage());
                    DialogUtil.showCommonAlertDialog("打印失败" + e.getMessage());
                }
            }

            @Override
            public void onFailure(Call<AjaxResult> call, Throwable t) {
                hideProcess();
                DialogUtil.showErrorAlertDialog(t.getMessage());
            }
        });
    }

    private void initToggleDataWidget() {

        binding.toggleData.setOnClickListener(v -> {
            String pageNo = binding.pageNoEdit.getText().toString();
            String requestUniParam = RequestUniParam.create(String.format("点击了切换数据按钮，切换前pageNo:%s，切换到：%s", expressPage.getPageNo(), pageNo)).toJson();
            showProcess();

            ApiServiceUtil.enqueue(() -> apiService.getExpressPage(pageNo, requestUniParam), new Callback<AjaxResult>() {
                @Override
                public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {
                    hideProcess();
                    AjaxResult ajaxResult = response.body();
                    if (ajaxResult.isSuccess()) {
                        JSONObject result = ajaxResult.getData(JSONObject.class);
                        JSONObject data = result.getJSONObject("data");
                        //填充数据,不弹框
                        int expressTypeIdIndex = getExpressTypeIdIndex(data.getString("expressTypeId"));
                        binding.expressType.setSelection(expressTypeIdIndex);
                        //暂时屏蔽同步
                        needSaveExpressPage = false;
                        nos.clear();
                        nos.addAll(data.getObject("nos", List.class));
                        needSaveExpressPage = true;
                        //修改pageNo
                        expressPage.setPageNo(pageNo);
                        ToastUtil.show("切换成功");
                    } else {
                        ToastUtil.show(ajaxResult.getMsg() + "，页面编码已重置");
                        binding.pageNoEdit.setText(expressPage.getPageNo());
                    }
                }

                @Override
                public void onFailure(Call<AjaxResult> call, Throwable t) {
                    hideProcess();
//                    ToastUtil.show("切换数据失败，请稍后尝试");

                    DialogUtil.showErrorAlertDialog(t.getMessage());
                    binding.pageNoEdit.setText(expressPage.getPageNo());
                }
            });
        });
    }

    private void reset() {

        showProcess();
        nos.clear();
        expressPage = new ExpressPage();
        expressPage.setNos(nos);
        initPageNo();
        String expressTypeId = SharedPreferencesUtil.getString("expressTypeId");
        if (expressTypeId != null) {

            int expressTypeIdIndex = getExpressTypeIdIndex(expressTypeId);
            binding.expressType.setSelection(expressTypeIdIndex);
            expressPage.setExpressTypeId(expressTypeId);
        }
        hideProcess();
    }

    private void initData() {
        expressPage = new ExpressPage();
        expressPage.setNos(nos);

        needSaveExpressPage = true;
    }

    //初始化nos监听器
    private void initNosListener() {
        //初始化nos listView布局
        binding.nos.setLayoutManager(new LinearLayoutManager(this));
        adapter = new OutStockApplyAdapter(nos, this);
        binding.nos.setAdapter(adapter);

        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
//        dividerItemDecoration.setDrawable(ContextCompat.getDrawable(this, R.drawable.custom_divider)); // 设置自定义分割线样式
        binding.nos.addItemDecoration(dividerItemDecoration);
        binding.nos.setItemAnimator(new DefaultItemAnimator());

        nos.addOnListChangedCallback(new ObservableList.OnListChangedCallback<ObservableList<String>>() {
            @SuppressLint("NotifyDataSetChanged")
            @Override
            public void onChanged(ObservableList<String> sender) {
                adapter.notifyDataSetChanged(); // 数据变化时通知适配器刷新列表
            }

            @Override
            public void onItemRangeChanged(ObservableList<String> sender, int positionStart, int itemCount) {
                adapter.notifyItemRangeChanged(positionStart, itemCount); // 通知适配器局部刷新
            }

            @Override
            public void onItemRangeInserted(ObservableList<String> sender, int positionStart, int itemCount) {
//                adapter.notifyItemRangeChanged(positionStart-1, itemCount); // 通知适配器局部刷新
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onItemRangeMoved(ObservableList<String> sender, int fromPosition, int toPosition, int itemCount) {
                adapter.notifyItemRangeRemoved(fromPosition, itemCount); // 通知适配器局部刷新
            }

            @Override
            public void onItemRangeRemoved(ObservableList<String> sender, int positionStart, int itemCount) {
                adapter.notifyItemRangeRemoved(positionStart, itemCount); // 通知适配器局部刷新
            }
        });
    }


    /**
     * 初始化物流方式组件
     */
    private void initExpressTypeWidget() {
        RequestUniParam requestUniParam = RequestUniParam.create("获取快递类型");
        showProcess();
        ApiServiceUtil.enqueue(() -> apiService.getExpressType(requestUniParam.toJson()), new Callback<AjaxResult>() {
            @Override
            public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {
                hideProcess();
                if (!response.isSuccessful()) {
                    ToastUtil.show("获取快递类型失败,服务器异常，请稍后重试");
                    return;
                }
                AjaxResult ajaxResult = response.body();
                boolean success = ajaxResult.isSuccess();
                if (success) {
                    expressTypes = ajaxResult.getDataListByClz(ExpressType.class);


                    ArrayAdapter<ExpressType> adapter = new ArrayAdapter<ExpressType>(ExpressActivity.this, android.R.layout.simple_spinner_item, expressTypes) {
                        @Override
                        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
                            if (convertView == null) {
                                convertView = LayoutInflater.from(getContext()).inflate(android.R.layout.simple_spinner_item, parent, false);
                            }

                            // 设置显示的文本为 dictLabel 字段
                            TextView textView = convertView.findViewById(android.R.id.text1);
                            textView.setText(expressTypes.get(position).getDictLabel());

                            return convertView;
                        }

                        @Override
                        public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
                            if (convertView == null) {
                                convertView = LayoutInflater.from(getContext()).inflate(android.R.layout.simple_spinner_dropdown_item, parent, false);
                            }

                            // 设置下拉框中每个选项的显示文本为 dictLabel 字段
                            TextView textView = convertView.findViewById(android.R.id.text1);
                            textView.setText(expressTypes.get(position).getDictLabel());

                            return convertView;
                        }
                    };
                    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                    binding.expressType.setAdapter(adapter);
                    //region 设置默认物流方式
                    String expressTypeId = SharedPreferencesUtil.getString("expressTypeId");
                    expressPage.setExpressTypeId(expressTypeId);

                    int expressTypeIdIndex = getExpressTypeIdIndex(expressTypeId);
                    //endregion

                    binding.expressType.setSelection(expressTypeIdIndex);

                    binding.expressType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                        @Override
                        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                            expressType = expressTypes.get(position);
                            expressPage.setExpressTypeId(expressType.getDictValue());
                            SharedPreferencesUtil.saveString("expressTypeId", expressType.getDictValue());
                        }

                        @Override
                        public void onNothingSelected(AdapterView<?> parent) {

                        }
                    });


                } else {
                    ToastUtil.show(ajaxResult.getMsg());
                }
            }

            @Override
            public void onFailure(Call<AjaxResult> call, Throwable t) {
                hideProcess();
                DialogUtil.showErrorAlertDialog(t.getMessage());
            }
        });
    }

    private int getExpressTypeIdIndex(String expressTypeId) {
        int expressTypeIdIndex = -1;
        for (int i = 0; i < expressTypes.size(); i++) {
            if (Objects.equals(expressTypes.get(i).getDictValue(), expressTypeId)) {
                expressType = expressTypes.get(i);
                expressTypeIdIndex = i;
                break;
            }
        }
        return expressTypeIdIndex;
    }


    public void initSystemScanData() {

        // 新建一个广播接收对象，实现数据接收和处理
        broadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                try {
                    String action = intent.getAction();
                    if (action == null) {
                        return;
                    }
                    String data = IntentUtil.getStringExtra(intent);

                    switch (action) {
                        case IntentUtil.INTENT_ACTIONS_DEFAULT_1:
                        case IntentUtil.INTENT_ACTIONS_DEFAULT_2:
                            onBroadcastReceiver(data);
                        default:
                            break;
                    }
                } catch (Exception e) {
                    DialogUtil.showCommonAlertDialog(e.getMessage());
                }
            }

            private void onBroadcastReceiver(String barcodeData) {

                LogUtil.file("接收到广播数据", barcodeData);
                if (progressCount.get() > 0) {
                    ToastUtil.showWait("请等待上一个结果返回");
                    return;
                }
                if (nos.contains(barcodeData)) {
                    ToastUtil.showError("数据重复");
                    return;
                }
                //如果是出库申请开头的数据那么就是outStockApplyNos
                if (barcodeData.indexOf("CKSQ") == 0 || barcodeData.indexOf("FHTZ") == 0) {
                    expressPageCopy = expressPage.copy();
                    expressPageCopy.getNos().add(barcodeData);
                    saveExpress(() -> nos.add(barcodeData));
                } else {
                    //非法数据
                    ToastUtil.showError("非法数据，请检查");
                    return;
                }
            }
        };
        intentFilter = new IntentFilter();
        intentFilter.addAction(IntentUtil.INTENT_ACTIONS_DEFAULT_1);
        intentFilter.addAction(IntentUtil.INTENT_ACTIONS_DEFAULT_2);
    }


    @Override
    protected void onResume() {
        super.onResume();
        // 注册广播接收器
        registerReceiver(broadcastReceiver, intentFilter);
    }

    /**
     * 保存页面数据
     */
    private void saveExpress(Runnable r1) {
        String requestUniParam = RequestUniParam.create("保存页面数据").toJson();
        showProcess();

        ApiServiceUtil.enqueue(() -> apiService.saveExpress(expressPageCopy, requestUniParam), new Callback<AjaxResult>() {
            @Override
            public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {
                hideProcess();
                AjaxResult ajaxResult = response.body();
                if (Objects.requireNonNull(ajaxResult).isSuccess()) {

                    String count = ajaxResult.getData(String.class);
                    ToastUtil.showSuccess("保存成功");
                    Optional.ofNullable(r1).ifPresent(Runnable::run);
                } else {
                    SoundPlayerUtil.playFail();
                    DialogUtil.showCommonAlertDialog(ajaxResult.getMsg());
                }
            }

            @Override
            public void onFailure(Call<AjaxResult> call, Throwable t) {
                hideProcess();
                DialogUtil.showErrorAlertDialog(t.getMessage());
            }
        });
    }

    private void initPageNo() {
        showProcess();
        String requestUniParam = RequestUniParam.create("初始化页面编码").toJson();
        apiService.getNextPageNoByPageType("express", requestUniParam).enqueue(new Callback<AjaxResult>() {
            @Override
            public void onResponse(Call<AjaxResult> call, Response<AjaxResult> response) {
                hideProcess();
                if (response.code() != 200) {
                    ToastUtil.show("获取页面编码失败,请退出页面重试");
                    return;
                }
                AjaxResult result = response.body();
                if (result.isSuccess()) {
                    String pageNo = result.getData(String.class);
                    binding.pageNoEdit.setText(pageNo);
                    expressPage.setPageNo(pageNo);
                    LogUtil.file("获取页面编码", "pageNo:" + pageNo);
                }
                //初始化测试数据
                if (BuildConfig.DEBUG) {
//                    initTestData();
                }
            }

            @Override
            public void onFailure(Call<AjaxResult> call, Throwable t) {
                hideProcess();
//                ToastUtil.show("获取页面编码失败,请退出页面重试");
                DialogUtil.showErrorAlertDialog(t.getMessage());
            }
        });
    }

    @Override
    public void remove(String datum) {
        expressPageCopy = expressPage.copy();
        expressPageCopy.getNos().remove(datum);
        saveExpress(() -> nos.remove(datum));
    }


    @Override
    protected void onPause() {
        if (broadcastReceiver != null) {
            unregisterReceiver(broadcastReceiver); // 取消广播注册
        }
        super.onPause();
    }
}